package GroupWare;

import java.util.LinkedList;

import DBUtil.CNN;
import Tools.Log;

/**
 * 文件字节缓存块，硬盘保护
 * 
 * @author Administrator
 * 
 */
public class ParcelBytes {

	public volatile static LinkedList<ParcelBytes> alpb = new LinkedList<ParcelBytes>();// 回收池
	private volatile static int count = 0;// 统计生产数量
	private volatile static int MaxSum = loadBufferSize();// 生产数量上限,全局缓存区大小，单位：MB
															// 缓存区越大对速度提升明显，太大会影响内存申请失败
	private volatile static int secondSize = 1048576;// 每块字节集的大小,默认1MB
	private static int oneSize = 1024;// 一级缓存大小
	/**
	 * 创建字节块，在线程中执行此方法，当回收站空且创建的数量已达到一定限度时候，程序会阻塞一段时间。
	 * 
	 * @param bt
	 * @param sum
	 * @param size
	 * @return
	 */
	public synchronized static ParcelBytes CreateParcelBytes(long offset_file) {
		if (alpb.size() == 0 && count < MaxSum) {
			return new ParcelBytes(offset_file);
		} else {
			ParcelBytes pb = null;
			while (alpb.size() == 0 || (pb = alpb.removeFirst()) == null) {// 从回收站中取出
				try {
					Thread.sleep(1);
				} catch (Exception e) {
				}
			}
			pb.setOffset_file(offset_file);// 标记相对文件字节块的偏移量
			return pb;
		}
	}
	public static int getBuffer() {
		return oneSize;
	}
	/**
	 * 获取字节块的大小
	 * 
	 * @return
	 */
	public static int getSecondBufferedSize() {
		return secondSize;
	}

	/**
	 * 加载缓冲池最大值配置
	 * 
	 * @return
	 */
	protected static int loadBufferSize() {
		if (MaxSum <= 0) {
			MaxSum = 20;// 默认值
			secondSize = 1048576;
			oneSize = 1024;
			try {
				MaxSum = Integer.parseInt((String) CNN.getConfig().GetPathValue("Transfers.Download:buffersize"));
				secondSize = Integer.parseInt((String) CNN.getConfig().GetPathValue("Transfers.Download:secondbuffer"));
				oneSize = Integer.parseInt((String) CNN.getConfig().GetPathValue("Transfers.Download:buffer"));
				if (oneSize <= 0) {
					oneSize = 1024;
				}
				if (secondSize <= 0) {
					secondSize = 1048576;
				}
				if (MaxSum <= 0) {
					MaxSum = 20;
				}
				Log.print("[ParcelBytes]size=" + MaxSum + "\tone_buf=" + oneSize + "\tsecond_buf=" + secondSize);
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
		return MaxSum;
	}

	public static void setBuffer(int buffer) {
		ParcelBytes.oneSize = buffer;
	}

	private long offset_file;// 相对文件的偏移量

	private int size;// 当前指针

	private byte[] bt;// 数据

	/**
	 * 构造字节段对象
	 * 
	 * @param bt
	 *            字节数据
	 * @param sum
	 *            数量
	 * @param offset
	 *            文件数据偏移量
	 */
	private ParcelBytes(long offset) {
		this.offset_file = offset;
		this.bt = new byte[secondSize];
		count++;
	}

	private boolean checkFull() {
		if (size >= this.bt.length) {
			return true;
		}
		return false;
	}

	/**
	 * 获取字节数据
	 * 
	 * @return
	 */
	public byte[] getBytes() {
		return bt;
	}

	/**
	 * 获取文件字节段的末尾偏移量。
	 * 
	 * @return
	 */
	public long getEnd() {
		return offset_file + size;
	}

	/**
	 * 获取相对文件偏移量
	 * 
	 * @return
	 */
	public long getOffset_file() {
		return offset_file;
	}

	/**
	 * 获取次缓冲区已写入数量
	 * 
	 * @return
	 */
	public int getSize() {
		return size;
	}

	/**
	 * 放入回收站
	 */
	public void reclaim() {
		size = 0;// 清空缓冲
		synchronized (alpb) {
			alpb.add(this);
		}
	}

	/**
	 * 定位字节块相对文件的偏移量
	 * 
	 * @param offset_file
	 */
	public void setOffset_file(long offset_file) {
		this.offset_file = offset_file;
	}

	@Override
	public String toString() {
		return "[Filebyte offset:" + offset_file + "end:" + getEnd() + "\tSum:" + size + "]";
	}

	/**
	 * 写入缓存
	 * 
	 * @param bts
	 *            欲写入数据
	 * @param bts
	 *            偏移量
	 * @param sum
	 *            数量
	 * @return 结束写入位置，如果返回值小于end说明溢出了字节。
	 */
	public int write(byte[] bts, int off, int end) {
		for (int i = off; i < end; i++) {
			if (checkFull())
				return i;
			this.bt[size++] = bts[i];// 拷贝字节数据
		}
		return end;
	}

}
